/******************************************************************************
 *  Include Files
 *****************************************************************************/
#include "COM.h"
#include "DRV_MSCAN.h"
#include "NVM.h"
#include "Bootloader.h"

/******************************************************************************
 *  Macro Definitions
 *****************************************************************************/
#define ID_Warning_C 0x1
#define ID_Bootload2Me_C 0x7FE
#define ID_Me2Bootload_C 0x7FF

/******************************************************************************
 *  Const Definitions
 *****************************************************************************/

/*****************************************************************************
 *  Global Variables Definitions
 *****************************************************************************/
static LDD_CAN_TFrame COM_ReadFrame_Bootloader = {
    .MessageID = ID_Bootload2Me_C,
    .FrameType = LDD_CAN_DATA_FRAME,
    .Data = 0,
    .Length = 8,
    .TimeStamp = 0,
    .LocPriority = 0};
static LDD_CAN_TFrame COM_SendFrame_Bootloader = {
    .MessageID = ID_Me2Bootload_C,
    .FrameType = LDD_CAN_DATA_FRAME,
    .Data = 0,
    .Length = 8,
    .TimeStamp = 0,
    .LocPriority = 10};
static LDD_CAN_TFrame COM_SendFrame_Warning = {
    .MessageID = ID_Warning_C,
    .FrameType = LDD_CAN_DATA_FRAME,
    .Data = 0,
    .Length = 8,
    .TimeStamp = 0,
    .LocPriority = 0};

static uint8_t COM_TxFrame_Data[8] = {0};
static uint8_t COM_RxFrame_Data[8] = {0};

uint8_t COM_Req = 0;

/*****************************************************************************
 *  Local Function declarations
 *****************************************************************************/
uint8_t COM_IsRxFull(void);
void COM_Read_Frame(void);
uint8_t COM_Read_Then_IsReq(void);
uint8_t COM_Read_Then_Check_Req(uint8_t Req);
void COM_Send_Resp(uint8_t Resp);

/*****************************************************************************
 *  Function Definitions
 *****************************************************************************/
void COM_Init(void) { COM_ReadFrame_Bootloader.Data = COM_RxFrame_Data; }

uint8_t COM_CheckLink(void) {
  if (0 != COM_IsRxFull()) {
    if (0 != COM_Read_Then_Check_Req(COM_BOOTLOADER_SHAKEHANDS_REQ)) {
      COM_Send_Resp(COM_BOOTLOADER_SHAKEHANDS_RESP);
      return 1;
    } else {
      return 0;
    }
  } else {
    return 0;
  }
}

uint8_t COM_IsRxFull(void) { return DRV_MSCAN_IsRxFull(); }

void COM_Read_Frame(void) { DRV_MSCAN_ReadFrame(&COM_ReadFrame_Bootloader); }

uint8_t COM_Read_Then_IsReq(void) {
  COM_Read_Frame();
  if (ID_Bootload2Me_C != COM_ReadFrame_Bootloader.MessageID) {
    return COM_BOOTLOADER_FRAMETYPE_OTHER;
  } else if (1 == COM_ReadFrame_Bootloader.Length) {
    COM_Req = COM_ReadFrame_Bootloader.Data[0];
    return COM_BOOTLOADER_FRAMETYPE_REQ;
  } else if (8 == COM_ReadFrame_Bootloader.Length) {
    return COM_BOOTLOADER_FRAMETYPE_DATA;
  } else {
    return COM_BOOTLOADER_FRAMETYPE_OTHER;
  }
}

uint8_t COM_Read_Then_Check_Req(uint8_t Req) {
  if ((COM_BOOTLOADER_FRAMETYPE_REQ != COM_Read_Then_IsReq()) ||
      (Req != COM_ReadFrame_Bootloader.Data[0])) {
    return 0;
  } else {
    return 1;
  }
}

void COM_Send_Resp(uint8_t Resp) {
  COM_SendFrame_Bootloader.Length = 1;
  COM_TxFrame_Data[0] = Resp;
  COM_SendFrame_Bootloader.Data = COM_TxFrame_Data;
  DRV_MSCAN_SendFrame(&COM_SendFrame_Bootloader);
}

void COM_Send_CheckSum(void) {
  COM_SendFrame_Bootloader.Length = 8;
  COM_TxFrame_Data[0] = COM_BOOTLOADER_CHECKSUM_RESP;
  COM_TxFrame_Data[1] = NVM_Checked_CHEKCSUM;
  COM_TxFrame_Data[2] = NVM_Checked_CHEKCSUM >> 8;
  COM_TxFrame_Data[3] = NVM_Checked_CHEKCSUM >> 16;
  COM_TxFrame_Data[4] = NVM_Checked_CHEKCSUM >> 24;
  COM_TxFrame_Data[5] = 0xFF;
  COM_TxFrame_Data[6] = 0xFF;
  COM_TxFrame_Data[7] = 0xFF;
  COM_SendFrame_Bootloader.Data = COM_TxFrame_Data;
  DRV_MSCAN_SendFrame(&COM_SendFrame_Bootloader);
}

uint8_t COM_Data2Buf(uint8_t Data_Buf[], uint8_t Data_Buf_cnt,
                     uint8_t DATABUFMAX) {
  uint8_t i = 0;
  if (Data_Buf_cnt + 8 <= DATABUFMAX) {
    for (i = 0; i < 8; i++) {
      Data_Buf[Data_Buf_cnt + i] = COM_ReadFrame_Bootloader.Data[i];
    }
    return Data_Buf_cnt + 8;
  } else {
    return Data_Buf_cnt;
  }
}

void COM_Send_Warning(void) {
  COM_TxFrame_Data[0] = 0;
  COM_TxFrame_Data[1] = 0;
  COM_TxFrame_Data[2] = 0;
  COM_TxFrame_Data[3] = 0;
  COM_TxFrame_Data[4] = 0;
  COM_TxFrame_Data[5] = 0;
  COM_TxFrame_Data[6] = 0;
  COM_TxFrame_Data[7] = 0;
  COM_SendFrame_Warning.Data = COM_TxFrame_Data;
  DRV_MSCAN_SendFrame(&COM_SendFrame_Warning);
}
